package com.hboxs.asl.pingpp.controller;

import com.hboxs.asl.JsonMessage;
import com.hboxs.asl.controller.app.member.OrderControl;
import com.hboxs.asl.entity.*;
import com.hboxs.asl.pingpp.service.PaymentService;
import com.hboxs.asl.service.*;
import com.pingplusplus.model.Charge;
import com.pingplusplus.model.Event;
import com.pingplusplus.model.EventData;
import com.pingplusplus.model.Webhooks;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Controller -- Ping++ 支付回调
 */
@Controller(value = "appPingppPaymentController")
@RequestMapping(value = "/app/m/pingpp/payment")
public final class AppPaymentController {

    protected Logger logger = Logger.getLogger(getClass());

    @Resource(name = "pingppPaymentServiceImpl")
    private PaymentService paymentService;
    @Resource(name = "memberServiceImpl")
    private MemberService memberService;
    @Resource(name = "orderServiceImpl")
    private OrderService orderService;
    @Resource(name = "tradeServiceImpl")
    private TradeService tradeService;
    @Resource(name = "orderSnServiceImpl")
    private OrderSnService orderSnService;
    @Resource(name = "questionServiceImpl")
    private QuestionService questionService;
    @Resource(name = "courseTradeServiceImpl")
    private CourseTradeService courseTradeService;
    @Resource(name = "yiYuanTradeServiceImpl")
    private YiYuanTradeService yiYuanTradeService;
    @Resource(name = "courseServiceImpl")
    private CourseService courseService;
    @Resource(name = "snServiceImpl")
    private SnService snService;
    @Resource(name = "globalConfigServiceImpl")
    private GlobalConfigService globalConfigService;

    /**
     * 购买课程
     * @param channel
     * @param request
     * @return
     */
    @RequestMapping(value = "/course_pay_android", method = RequestMethod.POST)
    public
    @ResponseBody
    Object coursePayAndroid(String channel, HttpServletRequest request, Long courseId, String note, String phone, String linkman) {

        try {
            Member member = memberService.getCurrentByToken();
            if(member == null) {
                return JsonMessage.USER_NOT_LOGIN;
            }
            if (phone == null || phone.isEmpty()) {
                return JsonMessage.error("手机不能为空");
            }
            if (linkman == null || linkman.isEmpty()) {
                return JsonMessage.error("联系人不能为空");
            }
            CourseTrade courseTrade = new CourseTrade();
            Course course = courseService.find(courseId);
            if(course != null) {
                courseTrade.setCourseId(course.getId());
                if(course.getMember() != null) {
                    courseTrade.setTeacherId(course.getMember().getId());
                }
                if(course.getMember().getAvator() != null) {
                    courseTrade.setTeacherAvator(course.getMember().getAvator());
                }
                if(course.getMember().getName() != null) {
                    courseTrade.setTeacherName(course.getMember().getName());
                }
                if(course.getCategory().getId() != null) {
                    courseTrade.setCategoryId(course.getCategory().getId());
                }
                if(course.getCategory().getName()!= null) {
                    courseTrade.setCategoryName(course.getCategory().getName());
                }
                if(course.getTitle() != null) {
                    courseTrade.setTitle(course.getTitle());
                }
                if(course.getImageURL() != null) {
                    courseTrade.setImageURL(course.getImageURL());
                }
                if(course.getIntroduction() != null) {
                    courseTrade.setIntroduction(course.getIntroduction());
                }
                if(course.getCharge() != null) {
                    courseTrade.setCharge(course.getCharge());
                }
                if(course.getEncrypt() != null) {
                    courseTrade.setEncrypt(course.getEncrypt());
                }
                if(course.getPassword() != null) {
                    courseTrade.setPassword(course.getPassword());
                }
                if(course.getPubdate() != null) {
                    courseTrade.setPubdate(course.getDatePattern());
                }
                if(course.getPrice() != null) {
                    courseTrade.setPrice(course.getPrice());
                }
                if(course.getCourseType() != null) {
                    if (course.getCourseType().equals(Course.CourseType.nolive)) {
                        courseTrade.setCourseType(CourseTrade.CourseType.nolive);
                    }
                    if (course.getCourseType().equals(Course.CourseType.live)) {
                        courseTrade.setCourseType(CourseTrade.CourseType.live);
                    }
                    if (course.getCourseType().equals(Course.CourseType.finished)) {
                        courseTrade.setCourseType(CourseTrade.CourseType.finished);
                    }
                }
            }
            courseTrade.setPubdate(course.getDatePattern());
            courseTrade.setBuyer(member);
            courseTrade.setNote(note);
            courseTrade.setHasReview(false);
            courseTrade.setPhone(phone);
            courseTrade.setLinkman(linkman);
            courseTrade.setPaymentStatus(CourseTrade.PaymentStatus.unpaid);
            courseTrade.setSn(snService.generate(Sn.Type.waste));
            courseTradeService.save(courseTrade);

            if (StringUtils.isEmpty(channel)) {
                return JsonMessage.error("支付通道不能为空");
            }

            Map<String, String> extra = new HashMap<>();

            return JsonMessage.success(
                    paymentService.simpleCharge(
                            courseTrade.getSn(),
                            channel,
                            ("15813317602".equals(member.getUsername()) ? "1" : String.valueOf(courseTrade.getPrice().multiply(new BigDecimal(100)).intValue())),
                            request.getRemoteHost(),
                            "订单",
                            courseTrade.getBuyer().getUsername() + " | 费用：" + courseTrade.getPrice(),
                            extra,
                            "COURSE"
                    )
            );

        } catch (Exception e) {
            e.printStackTrace();
        }
        return JsonMessage.UNKNOWN_ERROR;
    }


    /**
     * 购买课程
     * @param channel
     * @param sn
     * @param request
     * @return
     */
    @RequestMapping(value = "/coursePay", method = RequestMethod.POST)
    public
    @ResponseBody
    Object coursePay(String channel, String sn, HttpServletRequest request) {

        try {
            //1. 获取系统courseTrade
            CourseTrade courseTrade = courseTradeService.findBySn(sn);
            if (courseTrade == null) {
                return JsonMessage.error("订单不存在!");
            }
            //2.courseTrade是否属于当前用户
            Member member = memberService.getCurrentByToken();
            if (member == null) {
                return JsonMessage.USER_NOT_LOGIN;
            }
            if (courseTrade.getBuyer() != member) {
                return JsonMessage.error("订单不属于该用户!");
            }
            //3.判断order是否支付
            if (courseTrade.getPaymentStatus() == CourseTrade.PaymentStatus.paid) {
                return JsonMessage.error("订单已支付!");
            }

            //4.channel 不能为空
            if (StringUtils.isEmpty(channel)) {
                return JsonMessage.error("支付通道不能为空");
            }

            //6.准备pingpp参数
            Map<String, String> extra = new HashMap<>();

            return JsonMessage.success(
                    paymentService.simpleCharge(
                            courseTrade.getSn(),
                            channel,
                            ("15813317602".equals(member.getUsername()) ? "1" : String.valueOf(courseTrade.getPrice().multiply(new BigDecimal(100)).intValue())),
                            request.getRemoteHost(),
                            "订单",
                            courseTrade.getBuyer().getUsername() + " | 费用：" + courseTrade.getPrice(),
                            extra,
                            "COURSE"
                    )
            );

        } catch (Exception e) {
            e.printStackTrace();
        }
        return JsonMessage.UNKNOWN_ERROR;
    }


    /**
     * 支付提问费用
     * @param channel
     * @param sn
     * @param request
     * @return
     */
    @RequestMapping(value = "/quesionPay", method = RequestMethod.POST)
    public
    @ResponseBody
    Object quesionPay(String channel, String sn, HttpServletRequest request) {

        try {
            //1. 获取系统question
            Question question = questionService.findBySn(sn);
            if (question == null) {
                return JsonMessage.error("该易问易答不存在");
            }
            //2.question是否属于当前用户
            Member member = memberService.getCurrentByToken();
            if (member == null) {
                return JsonMessage.USER_NOT_LOGIN;
            }
            if (question.getMember() != member) {
                return JsonMessage.error("该易问易答不属于该用户!");
            }
            //3.判断question是否支付
            if (question.getPaymentStatus() == Question.PaymentStatus.paid) {
                return JsonMessage.error("该易问易答已支付!");
            }

            //4.channel 不能为空
            if (StringUtils.isEmpty(channel)) {
                return JsonMessage.error("支付通道不能为空");
            }

            //6.准备pingpp参数
            Map<String, String> extra = new HashMap<>();

            return JsonMessage.success(
                    paymentService.simpleCharge(
                            question.getSn(),
                            channel,
                            ("15813317602".equals(member.getUsername()) ? "1" : String.valueOf(question.getPayPrice().multiply(new BigDecimal(100)).intValue())),
                            request.getRemoteHost(),
                            "订单",
                            question.getMember().getUsername() + " | 费用：" + question.getPayPrice(),
                            extra,
                            "QUESTION"
                    )
            );

        } catch (Exception e) {
            e.printStackTrace();
        }
        return JsonMessage.UNKNOWN_ERROR;
    }


    /**
     * 一元偷听记录 支付
     * @param channel
     * @param sn
     * @param request
     * @return
     */
    @RequestMapping(value = "/yiyuanPay", method = RequestMethod.POST)
    public
    @ResponseBody
    Object yiyuanPay(String channel, String sn, HttpServletRequest request) {

        try {
            //1. 获取系统yiyuanTrade
            YiYuanTrade yiYuanTrade = yiYuanTradeService.findBySn(sn);
            if (yiYuanTrade == null) {
                return JsonMessage.error("订单不存在!");
            }
            //2.yiyuanTrade是否属于当前用户
            Member member = memberService.getCurrentByToken();
            if (member == null) {
                return JsonMessage.USER_NOT_LOGIN;
            }
            if (yiYuanTrade.getBuyer() != member) {
                return JsonMessage.error("订单不属于该用户!");
            }
            //3.判断yiyuanTrade是否支付
            if (yiYuanTrade.getPaymentStatus() == YiYuanTrade.PaymentStatus.paid) {
                return JsonMessage.error("订单已支付!");
            }

            //4.channel 不能为空
            if (StringUtils.isEmpty(channel)) {
                return JsonMessage.error("支付通道不能为空");
            }

            //6.准备pingpp参数
            Map<String, String> extra = new HashMap<>();

            return JsonMessage.success(
                    paymentService.simpleCharge(
                            yiYuanTrade.getSn(),
                            channel,
                            ("15813317602".equals(member.getUsername()) ? "1" : String.valueOf(yiYuanTrade.getPrice().multiply(new BigDecimal(100)).intValue())),
                            request.getRemoteHost(),
                            "订单",
                            yiYuanTrade.getBuyer().getUsername() + " | 费用：" + yiYuanTrade.getPrice(),
                            extra,
                            "YIYUAN"
                    )
            );

        } catch (Exception e) {
            e.printStackTrace();
        }
        return JsonMessage.UNKNOWN_ERROR;
    }


    /**
     * 余额支付接口 Json
     */
    @RequestMapping(value = "/balancePayJson", method = RequestMethod.POST)
    public
    @ResponseBody
    Object paymentBybalanceJson(String snsJson, HttpServletRequest request, Boolean isEncode) {

        try {

            if (isEncode != null && isEncode == true && snsJson != null) {
                snsJson = java.net.URLDecoder.decode(snsJson, "utf-8");
            }

            List<String> sns = OrderControl.changeJsonToSns(snsJson);
            Member member = memberService.getCurrentByToken();
            List<Order> orders = new ArrayList<>();
            BigDecimal totalOrderPayment = new BigDecimal(0);
            BigDecimal orderPoints = new BigDecimal(0);

            for (String sn : sns) {
                Order order = orderService.findBySn(sn);
                if (order == null || !member.equals(order.getMember()) || order.isExpired()) {
                    return JsonMessage.error("订单不存在");
                }
                if (order.getPaymentStatus().equals(Order.PaymentStatus.paid)) {
                    return JsonMessage.error("订单已支付");
                }
                totalOrderPayment = totalOrderPayment.add(order.getAmountPayable());
                orderPoints = orderPoints.add(order.getPayPoint());
                orders.add(order);
            }

            if (member.getBalance() == null || member.getBalance().compareTo(totalOrderPayment) < 0) {
                return JsonMessage.error("余额不足");
            }

            //判断用户积分
            if (member.getPoint().compareTo(orderPoints) < 0) {
                return JsonMessage.error("用户积分不足");
            }

            for (Order order : orders) {
                orderService.paymentByBalance(order);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return JsonMessage.UNKNOWN_ERROR;
        }
        return JsonMessage.success("支付成功");
    }


    /**
     * 充值
     */
    @RequestMapping(value = "/charge", method = RequestMethod.POST)
    public
    @ResponseBody
    Object charge(String channel, BigDecimal amount, HttpServletRequest request) {

        try {
            Member member = memberService.getCurrentByToken();
            if (member == null) {
                return JsonMessage.USER_NOT_LOGIN;
            }
            if (amount == null) {
                return JsonMessage.error("请传入充值金额");
            }
            if (StringUtils.isEmpty(channel)) {
                return JsonMessage.error("支付通道不能为空");
            }

            Map<String, String> extra = new HashMap<>();

            Trade trade = tradeService.create(member, amount, Trade.Style.pay);

            return JsonMessage.success(
                    paymentService.simpleCharge(
                            trade.getTn(),
                            channel,
                            String.valueOf(trade.getAmount().multiply(new BigDecimal(100)).intValue()),
                            request.getRemoteHost(),
                            "订单",
                            trade.getMember().getUsername() + " | 费用：" + trade.getAmount(),
                            extra, "ORDER"
                    )
            );

        } catch (Exception e) {
            e.printStackTrace();
        }
        return JsonMessage.UNKNOWN_ERROR;
    }

    /**
     * 支付成功回调！
     *
     * @param request request
     * @return string
     */
    @RequestMapping(value = "/pay_success_callback", method = RequestMethod.POST)
    @ResponseBody
    public Object pay_success_callback_post(HttpServletRequest request, HttpServletResponse response) {
        try {

            request.setCharacterEncoding("UTF8");
            // 获得 http body 内容
            BufferedReader reader = request.getReader();
            StringBuilder buffer = new StringBuilder();
            String string;
            while ((string = reader.readLine()) != null) {
                buffer.append(string);
            }
            Event event = Webhooks.eventParse(buffer.toString());
            EventData data = event.getData();
            Charge charge = (Charge) data.getObject();

            //获取订单号
            String snStr = charge.getOrderNo();

            // TODO: 测试是否可以行
            String description = charge.getDescription();

            if (snStr.startsWith(OrderSn.PFIX)) {
                snStr = orderSnService.find(Long.valueOf(snStr.split(OrderSn.PFIX)[1])).getSns();
            }
            String[] sns = snStr.split(",");

            for (int i = 0; i < sns.length; i++) {
                String sn = sns[i];

                // TODO: 使用 description 来判断支付类型
                if ("COURSE".equals(description)) {
                    CourseTrade courseTrade = courseTradeService.findBySn(sn);
                    if ("charge.succeeded".equals(event.getType())) {
                        //处理CourseTrade
                        courseTradeService.dealCourseTrade(charge, courseTrade);
                        response.setStatus(200);
                    } else if ("refund.succeeded".equals(event.getType())) {
                        response.setStatus(200);
                    } else {
                        response.setStatus(500);
                    }
                } else if ("QUESTION".equals(description)) {
                    Question question = questionService.findBySn(sn);
                    if ("charge.succeeded".equals(event.getType())) {
                        //处理question
                        questionService.dealQuestion(charge, question);
                        response.setStatus(200);
                    } else if ("refund.succeeded".equals(event.getType())) {
                        response.setStatus(200);
                    } else {
                        response.setStatus(500);
                    }
                } else if ("YIYUAN".equals(description)) {
                    YiYuanTrade yiYuanTrade = yiYuanTradeService.findBySn(sn);
                    if ("charge.succeeded".equals(event.getType())) {
                        //处理yiYuanTrade
                        yiYuanTradeService.dealYiYuanTrade(charge, yiYuanTrade);
                        response.setStatus(200);
                    } else if ("refund.succeeded".equals(event.getType())) {
                        response.setStatus(200);
                    } else {
                        response.setStatus(500);
                    }
                } else if ("ORDER".equals(description)) {
                    Trade trade = tradeService.findByTn(sn);
                    if ("charge.succeeded".equals(event.getType())) {
                        //处理充值成功
                        if (charge.getPaid()) {
                            if (!trade.getTradeStatus().equals(Trade.TradeStatus.done) && trade.getStyle().equals(Trade.Style.pay)) {
                                tradeService.completeTrade(trade);
                            } else {
                                logger.info(charge.getOrderNo() + " does not exist!");
                            }
                        } else {
                            logger.info(charge.getOrderNo() + " charge fail!");
                        }
                        response.setStatus(200);
                    } else if ("refund.succeeded".equals(event.getType())) {
                        response.setStatus(200);
                    } else {
                        response.setStatus(500);
                    }
                    return "charge-success";
                }
            }

            return "pay-success";
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 支付成功回调！
     *
     * @param request request
     * @return string
     */
    @RequestMapping(value = "/test", method = RequestMethod.GET)
    @ResponseBody
    public Object test(String sn, HttpServletRequest request, HttpServletResponse response) {
        Order order = orderService.findBySn(sn);
        orderService.dealOrder(null, order);
        return null;
    }

}
